package ar.edu.itba.it.pdc.httpParser;

import java.util.LinkedList;
import java.util.List;

import ar.edu.itba.it.pdc.httpParser.exceptions.HttpBadRequestException;
import ar.edu.itba.it.pdc.httpParser.interfaces.Parser;
import ar.edu.itba.it.pdc.httpParser.models.HttpHeaders;
import ar.edu.itba.it.pdc.httpParser.models.Token;
import ar.edu.itba.it.pdc.httpParser.models.TokenType;

public class HttpHeadersParser implements Parser {

	private enum State {
		LINESTART, NAME, VALUE, LINEEND
	};

	State state = State.LINESTART;

	List<Token> headerName = new LinkedList<Token>();
	List<Token> headerValue = new LinkedList<Token>();

	HttpHeaders model = new HttpHeaders();

	public int parseToken(Token token) throws HttpBadRequestException {

		switch (state) {

			case LINESTART:
				
				if (token.isType(TokenType.CRLF)) {
					
					return 0;
				} else if (token.isType(TokenType.WORD) || token.isType(TokenType.DIVIDE)) {
					
					state = State.NAME;
					return parseToken(token);
				} else {
	
					throw new HttpBadRequestException(token);
				}
			case NAME:
				if (token.isType(TokenType.WORD) || token.isType(TokenType.SPACE)
						|| token.isType(TokenType.DIVIDE)) {
					
					headerName.add(token);
				} else if (token.isType(TokenType.DOTS)) {
					
					state = State.VALUE;
				} else {
					throw new HttpBadRequestException(token);
				}
				break;
	
			case VALUE:
				if (token.isType(TokenType.WORD) || token.isType(TokenType.SPACE) || token.isType(TokenType.DIVIDE)
						|| token.isType(TokenType.DOTS)) {
					
					headerValue.add(token);
				} else if (token.isType(TokenType.CRLF)) {
					
					state = State.LINEEND;
//					state = State.LINESTART;
				} else {
					throw new HttpBadRequestException(token);
				}
				break;
			case LINEEND:
				
				if (token.isType(TokenType.SPACE)) {
					state = State.VALUE;
					return parseToken(token);
				} else {
					
					model.put(headerName, headerValue);
					headerName = new LinkedList<Token>();
					headerValue = new LinkedList<Token>();
					state = State.LINESTART;
					return parseToken(token);
				}
		}

		return -1;
	}

	@Override
	public HttpHeaders getModel() {
		return model;
	}

}
